#include "Scanner.h"

Scanner::Scanner(QString * content) : _content(content) {
    _tokens = new QVector<QString>();
}

QVector<QString> * Scanner::getTokens() const{
    return _tokens;
}

void Scanner::showErr(int * line,QString * ErrCont, int type){
    switch (type) {
    case 0:
            Console::print(Communicate::ERR_LINE+QString::number(*line)+(*ErrCont));
        break;
    default:
            Console::print(Communicate::WAR_LINE+QString::number(*line)+(*ErrCont));
        break;
    }
}

bool Scanner::scan() {

    QRegExp cyfra("[0-9]");
    QRegExp numerRuchu("[0-9]*\\.");
    QRegExp litery("[A-z]+");
    QRegExp wynik("(1/2-1/2)|(0-1)|(1-0)");
    QString token="";
    QRegExp ruch("((([K|Q|R|B|N|P]{0,1})([a-h]{0,1})([1-8]{0,1})([x]{0,1})([a-h])([1-8])(\\=([K|Q|R|B|N|P]{1})){0,1})||(O-O)||(O-O-O))([+]{0,1})");
    int typeOfComm = 0; //0 - ; //1 - {
    QChar znak;
    bool correct=true;

    int status=0;//0-wait for token //1-reading numerRuchu || wynik  //2-reading Komentarz //3-reading wynik //4-reading ciag //5-wartosc naglowka
    int lines=1;
    for (int a=0;a<(*_content).length();a++){
        znak = (*_content)[a];
        if (znak=='\n' || a==(*_content).length()-1){
            if (a==(*_content).length()-1){
                if (znak!='\n')
                    token+=znak;
            }
            if (token.length()>0){
                switch (status) {
                case 1:
                    if (numerRuchu.exactMatch(token))
                        _tokens->append("nR,"+token.mid(0,token.length()-1));
                    else{
                        showErr(& lines,& Communicate::ERR_NUM);
                        correct=false;
                    }
                    break;
                case 2:
                    if (typeOfComm==1){
                        showErr(& lines,& Communicate::ERR_COMM);
                        correct=false;
                    }else
                        _tokens->append("k,"+token);
                    break;
                case 3:
                    if (wynik.exactMatch(token))
                        _tokens->append("w,"+token);
                    else{
                        showErr(& lines,& Communicate::ERR_RES);
                        correct=false;
                    }break;
                case 4:
                    if (ruch.exactMatch(token))
                        _tokens->append("r,"+token);
                    else if (litery.exactMatch(token))
                        _tokens->append("cL,"+token);
                    else{
                        token=": Nieoczekiwany ciąg znaków: \""+token+"\"";
                        showErr(& lines, & token);
                        correct=false;
                    }
                    break;
                case 5:
                        showErr(& lines,& Communicate::ERR_HEA);
                        correct=false;
                    break;
                default:
                    break;
                }
                status=0;
                token="";
            }
            lines++;
            _tokens->append("br");
        }else if (status==2){
            if (znak=='}' && typeOfComm==1){
                _tokens->append("k,"+token);
                status=0;
                token="";
            }else
                token+=znak;
        }else if (status==5){
            if (znak=='"'){
                _tokens->append("wN,"+token);
                status=0;
                token="";
            }else
                token+=znak;
        }else if (znak==' '){
            if (token.length()>0){
                switch (status) {
                case 1:
                    if (numerRuchu.exactMatch(token))
                        _tokens->append("nR,"+token);
                    else{
                        showErr(& lines,& Communicate::ERR_NUM);
                        correct=false;
                    }
                    break;
                case 3:
                    if (wynik.exactMatch(token))
                        _tokens->append("w,"+token);
                    else{
                        showErr(& lines,& Communicate::ERR_RES);
                        correct=false;
                    }break;
                case 4:
                    if (ruch.exactMatch(token))
                        _tokens->append("r,"+token);
                    else if (litery.exactMatch(token))
                        _tokens->append("cL,"+token);
                    else{
                        token=": Niewłaściwy ciąg znaków: \""+token+"\"";
                        showErr(& lines, & token);
                        correct=false;
                    }
                    break;
                default:
                    break;
                }
                status=0;
                token="";
            }
        }else if (cyfra.exactMatch(znak)){
            if (status==0)
                status =1;
            token+=znak;
        }else if (znak=='-'){
            if (status==1)
                status=3;//to ma byc wynik
            token+=znak;
        }else if (znak=='.'){
            token+=znak;
            if (status==1){
                if (numerRuchu.exactMatch(token))
                    _tokens->append("nR,"+token.mid(0,token.length()-1));
                else{
                    showErr(& lines,& Communicate::ERR_NUM);
                    correct=false;
                }
                token="";
                status=0;
            }
        }else{
            if (status==0){
                if (znak=='{'){
                    status=2;
                    typeOfComm = 1;
                }else if (znak==';'){
                    status=2;
                    typeOfComm = 0;
                }else if (znak=='"'){
                    status=5;
                }else if (znak=='['){
                    _tokens->append("nP"+token);
                }else if (znak==']'){
                    _tokens->append("nK"+token);
                }else if (znak=='*'){
                    _tokens->append("w,"+token);
                }else{
                    status=4;
                    token+=znak;
                }
            }else{
                token+=znak;
            }
        }
    }
    if (correct){
        Console::print(Communicate::SCAN_OK);
    }
    return correct;
}

Scanner::~Scanner() {
    foreach(QString tok, *_tokens) {
//        qDebug()<<tok;
    }
    delete _tokens;
}
